貝老闆(週日下午三點、氣噗噗):小可我崩潰了!我叫 AI 把「只限週一到週五」的限制拿掉,結果它順手「優化」一堆東西——報表排版歪、金額變負數、時區還跳 UTC。😤
小可(拿出摺扇、深呼吸):那你怎麼處理?
貝老闆:我很棒,我學會用 Git 了!先 git revert 回上一版,世界和平。然後我又叫 AI「小改一下就好」——結果更壞。再改一次,又炸。越改越錯,我越看越火!
小可:你是讓 AI 直接改 code 然後 push 到 main 嗎?CI 有跑嗎?
貝老闆:AI 回我「All tests passed」。
小可(瞳孔微縮):我們根本沒有測試啊!😱 我只記得好威之前說過「不只使用者自己點一點」,還有一大串自動化測試——什麼 Unit、Integration、E2E、回歸、合約測試,還特別強調時間跟金額的邊界要寫死。AI 有幫我們跑那些嗎?
貝老闆:我不知道他說一切都完美了,給我一堆綠勾勾....
小可:別靠感覺,我們打給好威。
(電話轉擴音)
好威:兩位,有 AI 沒有測試等於有油門沒煞車。你們現在是在濕滑路面練甩尾:一次 revert 救回來,不代表下次不會再打滑。自動化測試要把規格鎖進程式裡,CI 要把每次改動關在鐵門內檢查——過關才放行。不然 AI 會「善意幫你整理」,順便整理出一車 Bug。😂
好威:齁,你一定都沒看三叔公的文章啦—— 葬送的軟體測試 - 不懂不想做是會出事,還不趕快去報名他的課!不過現在你先找 AI 叫他把「週末/月底/時區」寫成測試,叫它附上 GitHub Actions 範本,教你怎麼安裝吧....
踩坑現場
好威解析(白話科普)
Unit Test 是安全氣囊:小改動最怕牽一髮動全身。把「日期、金額、權限」這種規則寫成可重複驗證的測試,誰改都不怕。
CI Pipeline 是大門口的警衛:每次提交都跑 Lint、Test、Build。過關才給 merge/deploy。人會累,機器不會。
先測風險最高的邊界:週末、月底、跨年、夏令時間、時區切換……這些都是「禮拜天才會壞」的典型地雷。
主分支(main)要上鎖:開啟 Protected Branch、要求 PR、要求通過檢查與最小覆蓋率。
概念拆解(實務化)
1️⃣ Unit Test 基礎與策略
寫 Unit Test 就像把規格釘死在文件以外的地方:程式本身。先從純函式與規則密集處下手,如計費、時間、權限。每個測試描述一個情境(Given/When/Then),覆蓋正常值、邊界值、異常值。別追求一次到位的 100% 覆蓋率,先鎖住商務關鍵路徑(Happy Path)與兩三個最危險邊界,形成最小可行防線。
2️⃣ 風險導向的測試清單
把「最可能把你搞死」的情境先寫測試:週末/月底/跨月、夏令時間切換、台北與 UTC 的時區差、折扣上下限、金額四捨五入規則、權限判斷(管理員/一般用戶)。清單化後,每次改動對照新增或更新測試,不要只測你相信會過的,請刻意找麻煩。
3️⃣ 最小可用 CI Pipeline
CI 不需要一次搞超完整。第一版就三關:Lint(風格+潛在錯誤)、Test(單元測試與報告)、Build(可部署產物)。在 GitHub Actions 或 GitLab CI 設一條主幹流程,每個 PR 自動觸發,失敗就擋下。加上 Cache 與 Matrix 讓速度可接受;部署前再加「需要人為批准」與「只允許從 Release Branch 部署」。
4️⃣ Branch 與 Gate 設定
把 main 設為 Protected Branch:必須經過 PR、至少一位 Reviewer、必須通過 CI 檢查、並達到最低測試覆蓋率(先 60~70% 即可)。針對熱修(Hotfix)也走同一條管道,禁止直接推 Production。若有週末值班,改用 Feature Flag 灰度打開,而非直接把邏輯硬改上線。
迷你範例(Python)
用途:示範如何先寫邊界測試,再掛上最小 CI。
# billing.py
from datetime import datetime
import pytz
def weekend_surcharge(amount: int, dt: datetime, tz: str = "Asia/Taipei") -> int:
local = dt.astimezone(pytz.timezone(tz))
# 週六(5)、週日(6)加收 10%
if local.weekday() >= 5:
return int(round(amount * 1.1))
return amount
# test_billing.py
from datetime import datetime
import pytz
from billing import weekend_surcharge
def test_weekend_in_taipei_has_surcharge():
dt = pytz.timezone("Asia/Taipei").localize(datetime(2025, 8, 10, 12, 0)) # 週日
assert weekend_surcharge(100, dt) == 110
GitHub Actions 最小流程(用途:PR 觸發 Lint+Test)
# .github/workflows/ci.yml
name: ci
on: [pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with: { python-version: '3.12' }
- run: pip install -U pip pytest
- run: pytest -q
Takeaways
週末不上測試,就等著週末上新聞。測試是成本,但沒有測試是更大的成本;CI 是流程,但沒有流程就是災難的流程。先擋掉 80% 可預見的錯誤,剩下 20% 才需要英雄。
立即行動
今日提問
你的系統有哪些「只在週末/月底才會壞」的邏輯?請寫下三個,並描述你會如何把它們變成 Unit Test 的情境(Given/When/Then)。
Prompt 小作業
把這段提示貼給你的 AI 夥伴,套在你的專案:
「請閱讀我的專案 README 與 requirements.txt,幫我產生三個最關鍵的 Unit Test(涵蓋:週末/月底/時區),並建立一份最小 GitHub Actions ci.yml,要求在 PR 觸發時跑 pytest。若偵測到主分支未受保護,產生對應的設定步驟與風險說明。」